#ifndef NETWORK_H
#define NETWORK_H



#include "includes.h"
#include "players.h"



/** @brief Class for communication with the server
*
*   \image html network.jpeg
*/
class Client: public QTcpSocket
{

	Q_OBJECT

public:

	/** @brief Constructor only connects Qt signals and slots to minitor the socket
	*	@param parent Qt parent
	*/
	Client( QObject* parent = 0 );
	//! Destructor only disconnects form host
	~Client();

	/** @brief Sends string to the server
	*	@param s message to send
	*/
	void send_string( const string& s );


private:

	//! received message size
	quint16 block_size;

	/** @brief	Reads string from socket whnen message arrives
	*	@return	received message
	*/
	string read_string();


private slots:

	//! @brief Qt slot that reads and parses incomming message and runs appropriate actions
	void receive_message();

	/** @brief Qt slot informing about changed network connection status
	*	@param state new status
	*/
	void status_changed( const QAbstractSocket::SocketState& state );

	/** @brief Qt slot informing about network connection error
	*	@param error network error
	*/
	void connection_error( const QAbstractSocket::SocketError& error );

	//! @brief Qt slot invoked when connection is established
	void slot_connected();


signals:

	//! @brief Qt singnal that sends commands to game core
	void send_command( player*, const string& );

};



/** @brief Singleton to hnadle the network connection
*
*   \image html network.jpeg
*/
class network_client
{

public:
	
	/**	@brief	Function for obaining the singleton
	*	@return	pointer to the singleton
	*/
	static network_client* get_instance();

	//! @brief Closes the socket and resets the name, address, port number and underlying socket descriptor
	void rebuild()
	{
		client->deleteLater();
		client = new Client();
	};

	//! pointer to the network client ( QTcpSocket )
	Client* client;

	/** @brief Sets player information for sending over network
	*	@param typ player's type
	*	@param name player's name
	*/
	void set_player( const string& name, unsigned int typ );
	/** @brief Sets player's algorithm name for future association of algorithm to him
	*	@param alg_name algorithm name
	*/
	void set_players_algorithm( const string& alg_name );
	/** @brief	Gets player's information to send over network
	*	@return	player's information
	*/
	string get_player();
	/** @brief	Gets player's algorithm name for associating of algorithm to him
	*	@return algorithm name
	*/
	string get_players_algorithm();

	/** @brief Sets the id with which is client identified on server side
	*	@param id received id
	*/
	void set_net_id( unsigned int id )
	{
		my_network_id = id;
	};

	/** @brief	Gets the id with which is client identified on server side
	*	@return	network id number
	*/
	unsigned int get_net_id()
	{
		return my_network_id;
	};

	/** @brief Connects to server
	*	@param address server address
	*	@param port server port
	*/
	void connect_server( const string& address, int port );

	/** @brief Sends command to the server
	*	@param pl player, that executes the command
	*	@param cmd command
	*/
	void deliver_command( player* pl, const string& cmd );


	int x;


private:

	network_client( int _x): x( _x )
	{
		client = new Client();
	};
	network_client( const network_client& );
	network_client& operator=( const network_client& x );
	//! @brief Disconnects from host and deletes client
	~network_client()
	{
		client->deleteLater();
	};


	//! string identifiing the player ( sent to server when connected )
	string player_str;

	//! string identifiing player's algorithm for ai players
	string player_algorithm;

	//! id with which is client identified on server side
	unsigned int my_network_id;

};



#endif